#include "Lista.h"
#include <stdio.h>
#include <malloc.h>
#include <memory.h>
#include <stdbool.h>

void lista_Crear(TLista *pLs, int TamanioDato){
	pLs->Corriente = NULL;
	pLs->Primero = NULL;
	pLs->TamanioDato = TamanioDato;
}

void lista_Vaciar(TLista *pLs){
	TNodo *pNodo, *siguiente;
	for(pNodo = pLs->Primero;(pNodo);pNodo=siguiente){
		siguiente = pNodo->Siguiente;
		free(pNodo->Elem);
		free(pNodo);
	}
	pLs->Primero=pLs->Corriente=NULL;
}

int lista_Vacia(TLista Ls){
	return (Ls.Primero == NULL);
}

void lista_ElemCorriente(TLista Ls, void *pE){
	memcpy(pE, Ls.Corriente->Elem, Ls.TamanioDato);
}

void lista_ModifCorriente(TLista *pLs, void* pE){
	memcpy(pLs->Corriente->Elem, pE, pLs->TamanioDato);
}

int lista_MoverCorriente(TLista *pLs, TMovimiento M){
	void *aux; //declaro una variable auxiliar

	switch (M){
		case LSC_PRIMERO:
			pLs->Corriente=pLs->Primero;
			if (pLs->Corriente==NULL)	//se agrega if para saber si la lista esta vacia
				return false;
			break;
		
		case LSC_SIGUIENTE:
			if (pLs->Corriente==NULL)	//se agrega if para saber si la lista esta vacia
				return false;
			if (pLs->Corriente->Siguiente==NULL)
				return false;
			else
				pLs->Corriente=pLs->Corriente->Siguiente;
			break;
		
		case LSC_ANTERIOR:
			if (pLs->Corriente==NULL)	//se agrega if para saber si la lista esta vacia
				return false;
			if (pLs->Primero==pLs->Corriente)
				return false; //estoy en el primero, no hay anterior
			else{
				aux=pLs->Corriente; //recuerdo cual es la posicion actual
				pLs->Corriente=pLs->Primero; // me paro en el primero
				while (pLs->Corriente->Siguiente!=aux) //me fijo si el siguiente es distinto al que busco
					pLs->Corriente=pLs->Corriente->Siguiente; // entonces paso al siguiente
			}
	}
	return true;
}

void lista_BorrarCorriente(TLista *pLs){
	TNodo *PNodo=pLs->Corriente;
	if (pLs->Corriente==pLs->Primero){
		pLs->Primero = pLs->Corriente->Siguiente;
		pLs->Corriente = pLs->Primero;
	}
	else{
		TNodo *PAux=pLs->Primero;
		while (PAux->Siguiente!=pLs->Corriente)
			PAux = PAux->Siguiente;
		PAux->Siguiente=pLs->Corriente->Siguiente;
		if (PAux->Siguiente) //Si no es el �ltimo
			pLs->Corriente = PAux->Siguiente;
		else
			pLs->Corriente = PAux; //Si es el �ltimo queda en el anterior al borrado
	}
	free(PNodo->Elem);
	free(PNodo);
}

int lista_Insertar(TLista *pLs, TMovimiento M, void* pE){
	TNodo *pNodo = (TNodo*) malloc(sizeof(TNodo));
	if (!pNodo)
		return false; //No hay memoria disponible

	if ((pLs->Primero == NULL) || (M==LSC_PRIMERO) ||
		((M==LSC_ANTERIOR) && (pLs->Primero==pLs->Corriente)))		{
			//Si est� vac�a o hay que insertar en el primero o
			//hay que insertar en el anterior y el actual es el primero
		pNodo->Siguiente = pLs->Primero;
		pLs->Primero = pLs->Corriente = pNodo;
	}
	else{
		if (M == LSC_SIGUIENTE){
			pNodo->Siguiente = pLs->Corriente->Siguiente;
			pLs->Corriente->Siguiente = pNodo;
		}
		else{ //LS_ANTERIOR
			TNodo *pAux=pLs->Primero;
			while (pAux->Siguiente!=pLs->Corriente)
				pAux = pAux->Siguiente;
			pAux->Siguiente = pNodo;
			pNodo->Siguiente = pLs->Corriente;
		}
	}
	pNodo->Elem = malloc (pLs->TamanioDato);
	memcpy(pNodo->Elem, pE, pLs->TamanioDato);
	pLs->Corriente=pNodo;
	return true;
}
